package com.chalmers.foa.gamemodel.gameobjects.other.impl;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import android.graphics.Bitmap;
import android.graphics.Point;
import android.util.Log;

import com.chalmers.foa.gamehandlers.impl.CollisionHandler;
import com.chalmers.foa.gamehandlers.impl.PhysicsHandler;
import com.chalmers.foa.gamemodel.events.IEvent;
import com.chalmers.foa.gamemodel.gameobjects.BitmapType;
import com.chalmers.foa.gamemodel.gameobjects.GameObjectBitmapAdapter;
import com.chalmers.foa.gamemodel.gameobjects.IGameObject;
import com.chalmers.foa.gamemodel.gameobjects.IGameObjectEventCastable;
import com.chalmers.foa.gamemodel.gameobjects.effects.ParticleEffect;
import com.chalmers.foa.gamemodel.gameobjects.effects.impl.DismemberEffect;
import com.chalmers.foa.gamemodel.gameobjects.hazards.impl.Spike;
import com.chalmers.foa.gamemodel.gameobjects.obstacles.IMovableObstacle;
import com.chalmers.foa.util.BitmapInitiator;
import com.chalmers.foa.util.NewList;

public class Enemy extends GameObjectBitmapAdapter implements IGameObjectEventCastable, IMovableObstacle{
	
	private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
	
	private static final int VELOCITYH = 2;
	private static final int MAXSPEED = 16;
	
	private Point velocity, offset;
	private Bitmap[] bitmaps;
	private ParticleEffect dismemberEffect;
	private NewList collidingObjects;
	private IGameObject collidingObject;
	private IEvent event;
	
	public Enemy(Point position, Bitmap _bitmap,int layer,int bound) {
		super(_bitmap,position,layer,bound, false, true, false, true);
		velocity = new Point(VELOCITYH,0);
		offset = new Point();
		bitmaps = new Bitmap[4];
		dismemberEffect = new DismemberEffect(position, this.getColors());
		collidingObjects = new NewList(10);
		BitmapInitiator.initiateBitmaps(bitmaps, _bitmap);
	}
	
	public Enemy(Bitmap bitmap) {
		this(new Point(0,0),bitmap,0,-1);
	}
	public ParticleEffect getParticleEffect(){
		return dismemberEffect;
	}
	
	@Override
	public void update() {
		if(velocity.x > 0 && PhysicsHandler.getInstance().getGravity() > 0)
	    	setBitmap(BitmapType.DownRight);
	    else if(velocity.x < 0 && PhysicsHandler.getInstance().getGravity() > 0)
    	setBitmap(BitmapType.DownLeft);
	    else if(velocity.x > 0 && PhysicsHandler.getInstance().getGravity() < 0)
	    	setBitmap(BitmapType.UpRight);
	    else if(velocity.x < 0 && PhysicsHandler.getInstance().getGravity() < 0)
	    	setBitmap(BitmapType.UpLeft);
		
		move();
	}
	
	private void move() {
		PhysicsHandler.getInstance().applyGravitationToOffset(velocity);
		adjustSpeedToMaxSpeed();
		
		CollisionHandler.getInstance().objectsCollidingWithObject(this, 
				velocity, collidingObjects);
		offset.x = velocity.x;
		offset.y = velocity.y;
		CollisionHandler.getInstance().validateOffset(this, 
				offset);
		
		if(collidingObjects != null)
			for(int i = 0; i < collidingObjects.getSize(); i++) {
				collidingObject = collidingObjects.getObjectAt(i);
				if(collidingObject.isAlive()) {
					if(collidingObject instanceof Enemy && collidingObject.isAlive()) {
						CollisionHandler.getInstance().alignOffsetToObject(this, offset, collidingObject);
						break;
					}
					else if (collidingObject instanceof Spike) {
						pcs.firePropertyChange(new PropertyChangeEvent(this,
								"enemyKilled", null, null));
						kill();
					}
				}
			}
		
		if(offset.x == 0)
			reverseHorizontalVelocity();
		if(offset.y == 0)
			velocity.y = 0;
		if(offset.y > 0)
			offset.x = 0;
		else if(offset.y < 0)
			offset.x = 0;
		translate(offset.x, offset.y);
	}
	
	private void adjustSpeedToMaxSpeed() {
		if(velocity.x > MAXSPEED)
			velocity.x = MAXSPEED;
		else if(velocity.x < -MAXSPEED)
			velocity.x = -MAXSPEED;
		if(velocity.y > MAXSPEED)
			velocity.y = MAXSPEED;
		else if(velocity.y < -MAXSPEED)
			velocity.y = - MAXSPEED;
	}
	
	private void reverseHorizontalVelocity() {
		velocity.x = -velocity.x;
	}
	
	public void kill() {
		setAlive(false);
		if(hasEvent()){
			Log.v("Respawn 1","");
			triggerEvent();
		}
	}
	
	public int getHorizontalVelocity() {
		return VELOCITYH;
	}
	
	public void revertToStartPosition() {
		super.revertToStartPosition();
		setAlive(true);
	}

	private void setBitmap(BitmapType state){
		bitmap = bitmaps[state.ordinal()];
	}
	public void setVelocity(float _speedMultiplier){
		velocity.x = (int)(velocity.x*_speedMultiplier);
	}
	@Override
	public void addPropertyChangeListener(PropertyChangeListener pcl) {
		pcs.addPropertyChangeListener(pcl);
	}

	@Override
	public void triggerEvent() {
		if(event!=null)
			pcs.firePropertyChange(new PropertyChangeEvent(this, "respawn", null, event));
	}

	@Override
	public void bindEvent(IEvent _event) {
		event=_event;
	}

	@Override
	public boolean hasEvent() {
		return event!=null;
	}

	@Override
	public Point getVelocity() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setVelocity(Point velocity) {
		// TODO Auto-generated method stub
		
	}
	
}
